home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / presto / presto10.lha / src / threads.h < prev    next >
C/C++ Source or Header  |  1991-12-11  |  7KB  |  255 lines

  1. #ifndef __presto__threads_h__
  2. #define __presto__threads_h__
  3.  
  4. class SynchroObject;
  5. class Process;
  6. class Thread;
  7. class ThreadQ;
  8. class Scheduler;
  9. class Callstate;
  10.  
  11. extern Thread *systhread;
  12.  
  13. extern private_t Thread    *thisthread;    // always refers to running thread
  14. extern Process* thisproc;
  15.         
  16. #define TF_SCHEDULER    0x01        /* special thread.  Loops only */
  17. #define TF_KEEPSTACK    0x02        /* dont init stack on runrun */
  18. #define TF_INCOMPLETE    0x04        /* must acquire a stack before run */
  19. #define TF_NONPREEMPTABLE 0x08        /* can not preempt */
  20. #define TF_WILLJOIN    0x20        /* someone will join on it */
  21.  
  22.  
  23. #define TS_IDLE        0x01        /* useful, but not started    */
  24. #define TS_RUNNING    0x02        /* busy                */
  25. #define TS_READY    0x04        /* living in the readyq        */
  26.  
  27. #define TS_BLOCKED    0x20        /* blocked.  Don't care on what */
  28.  
  29. #define TS_LOCKED    0x80        /* unused            */
  30. #define TS_STOPPED    0x100        /* thread is unconditionally stopped */
  31.  
  32. #define TS_VIRGIN    0x400        /* thread not yet begun     */
  33. #define TS_ERROR    0x800        /* something amiss        */
  34. #define TS_DELETE    0x1000        /* no more trips to bed        */
  35. //
  36. // FINISHED should be part of the flags and not the state.
  37. //
  38. #define TS_FINISHED    0x2000        /* all done */
  39. #define TS_ANY        (~0)        /* matches all */
  40. #define TP_BASEPRIO    0        /* base priority */
  41.  
  42.  
  43.  
  44. //
  45. // WARNING: A CHANGE TO THIS CLASS OR ANY OF ITS BASE CLASSES MAY REQUIRE
  46. // RECOMPUTING THE STRUCT OFFSETS USED IN swtch!!
  47. //
  48.  
  49. class Stack;
  50. class Thread : public Object    {
  51. protected:
  52.     // *** The offsets of t_csp, t_fp and t_proc are known to swtch().
  53.     int    *t_csp;            // current stack pointer
  54.     int    *t_fp;            // frame pointer
  55.     Process    *t_proc;        // who is running me now
  56. #ifdef FPU_PREEMPT
  57.     // *** The offset of t_usingfpu is also known to swtch().
  58.     int    t_usingfpu;
  59. #endif /* FPU_PREEMPT */
  60.         Stack   *t_stack;               // thread's stack
  61.         int     t_stack_size;           // size of stack
  62.     int    t_state;        // current state
  63.     int     t_flags;        // internal only flags
  64. #ifdef sun
  65.     int     t_pc;
  66. #endif /* sun */
  67. #ifdef vax
  68.     int    t_pc;            // needed for Ultrix preemption
  69. #endif /* vax */
  70. #ifdef PROFILE
  71.     int qThread;
  72. #endif
  73.     int    t_tag;            // given tag on birth (UNIQUE)
  74.     int    t_tid;            // user's tag name
  75.     int    t_pri;            // thread priority
  76.     int    t_expired;        // true iff timeslice expired
  77.     int    t_slockcount;        // number of spinlocks held/spinning
  78.     Objany    t_data;            // for getdata/setdata
  79.     Objany        t_boundobj;    // what we are bound to
  80.     Callstate    t_callstate;    // initial call state
  81.     SynchroObject    *t_blockedon;    // Synchro object we are blked on 
  82. // redo    
  83.     union    {
  84.         Thread*        thread;    // thread waiting
  85.         Objany        value;    // ready value
  86.     } ut_join;
  87. #define t_jthread        ut_join.thread
  88. #define t_jvalue        ut_join.value
  89.     virtual    void    t_start1(Objany obj);    // second half of fork/start
  90. public:
  91.     Thread(char* name=0, int tid = 0, long ssiz = DEFSTACKSIZ);
  92.     Thread(int tid);
  93.     virtual Thread* newthread(char* name=0, int tid = 0,    // vtl ctr
  94.          long ssiz = DEFSTACKSIZ);
  95.     void *operator new(size_t);
  96.     void operator delete(void *);
  97.     virtual ~Thread();                // nuke a thread
  98. #define NOJOIN      0
  99. #define WILLJOIN TF_WILLJOIN
  100. #ifdef mips
  101.     /* Mips does not support var args well. */
  102.     virtual int     start(Objany obj, PFany pf, Objany arg = 0);
  103.             // Usage: thisthread->fork({NO,WILL}JOIN, ...)
  104.     virtual Thread* fork(int needjoin, Objany obj, PFany pf, 
  105.             Objany arg = 0);    
  106. #else    
  107.     virtual int     start(Objany obj, PFany pf, ...);    // enqueue
  108.             // Usage: thisthread->fork({NO,WILL}JOIN, ...)
  109.     virtual Thread* fork(int needjoin, Objany obj, PFany pf, ...);
  110. #endif /* mips */
  111.     virtual int     runrun();        // LIFE STARTS HERE 
  112.     virtual int     run();
  113.     void    swtch();            // back to the sched thread
  114.     virtual void     sleep(SynchroObject* so = 0);    // relinquish
  115.     virtual void     wakeup(SynchroObject* so = 0);    // resume
  116.     virtual void    willjoin();        // want to join
  117.     virtual Objany    join();            // please join
  118.     virtual void    terminate(Objany retobj=0);    // thread is finished
  119. //    virtual void     setaffinity(Process* p);    // mark affinity
  120.     void    setdata(Objany data)
  121.         { t_data = data; }
  122.     Objany  getdata()
  123.         { return t_data; }
  124.     void    setstate(int newstate)
  125.         { t_state = newstate; }
  126.     void    orstate(int st)
  127.         // { ATOMIC_ORL(&t_state, st); }
  128.         { t_state |= st; }
  129.     void    andstate(int st)
  130.         // { ATOMIC_ANDL(&t_state, st); }
  131.         { t_state &= st; }
  132.     void    isready()
  133.         { orstate(TS_READY); }
  134.     void    setflags(int newflags)
  135.         { t_flags = newflags; }
  136.     void    holdingspinlock()
  137.         { t_slockcount++; }
  138.     void    releasingspinlock()        
  139.         { t_slockcount--; }
  140.     int    inspinlock()
  141.         { return(t_slockcount); }
  142.     inline Stack    *stack();
  143.     int    *csp()
  144.         { return t_csp; }        
  145.     int    flags()
  146.         { return t_flags; }
  147. #ifdef sun
  148.     void    setpc(int pc)
  149.         {t_pc = pc;}
  150.     int    getpc()
  151.         {return t_pc;}
  152. #endif /* sun */
  153. #ifdef vax
  154.     void    setpc(int pc)
  155.         {t_pc = pc;}
  156.     int    getpc()
  157.         {return t_pc;}
  158. #endif /* vax */
  159.     int     state()
  160.         { return t_state; }
  161.     int    tag()    
  162.         { return t_tag; }
  163.     int    tid()
  164.         { return t_tid; }        
  165.     void    setpri(int newpri)    // beware of multiple writers
  166.         { t_pri= newpri; }
  167.     int     getpri()
  168.         { return t_pri; }
  169.     void     setproc(Process* p)
  170.         { t_proc = p; }
  171.     Process *getproc()
  172.         { return t_proc; }
  173.     Process **proc()
  174.         { return &t_proc; }
  175.     inline void    isrunning();    // mark thread running
  176.     void        isrunning2();    // but wait until it is done running
  177.     inline void    isnotrunning(); // as set by someone else
  178. #ifdef PROFILE
  179.     inline int    getqThread()
  180.         { return qThread; }
  181. #endif
  182.     int stackcnt()
  183.         { return stack()->numstacksbuilt(); }
  184.     int tagcnt();
  185.     // 
  186.     // Preemption related cruft
  187.     //
  188.     void preemptable()
  189.         { t_flags &= ~TF_NONPREEMPTABLE; }
  190.     void nonpreemptable()
  191.         { t_flags |= TF_NONPREEMPTABLE; }
  192.     int ispreemptable()
  193.         { return ( (t_flags & TF_NONPREEMPTABLE) == 0 ); }
  194. #ifdef FPU_PREEMPT
  195.     void usingfpu()
  196.         { t_usingfpu = 1; }
  197.     void notusingfpu()
  198.         { t_usingfpu = 0; }
  199.     int isusingfpu()
  200.         { return (t_usingfpu); }
  201. #endif /* FPU_PREEMPT */
  202.     double cputime();        // in seconds
  203.     int canpreempt();
  204.     virtual void  print(ostream& = cout);
  205. friend class ThreadQ;
  206. friend class ThreadQUnlocked;
  207. };
  208.  
  209. //
  210. // Mark a thread as running.  This should be called before
  211. // runrun.  If the thread is already running, the caller will
  212. // wait. This guarantess that we don't have two scheduling threads
  213. // trouncing on this poor thread's stack. One guy coming down
  214. // into runrun, while the other guy is trying to return from it.
  215. // We don't have to lock anything, since there is only one ordering of
  216. // ops on the state that can cause problems, 
  217. // and the problems are solved by delaying the
  218. // second thread here.
  219. //
  220.  
  221.  
  222. inline void
  223. Thread::isrunning()
  224. {
  225.  
  226.     if (t_state&TS_RUNNING)
  227.         (void)isrunning2();        // looping wait
  228.     orstate(TS_RUNNING);
  229. }
  230.  
  231.  
  232. //
  233. // This should be called after runrun
  234. //
  235. inline void
  236. Thread::isnotrunning()
  237. {
  238.     // if not finished, and not running, balk
  239.     if ( ((t_state&TS_FINISHED) == 0) && ((t_state&TS_RUNNING)== 0)    )
  240.         error("Thread is already not running\n");
  241.     else
  242.         andstate(~TS_RUNNING);
  243. }
  244.  
  245. inline
  246. Stack*
  247. Thread::stack()    
  248. {
  249.     if (t_flags&TF_INCOMPLETE) 
  250.         error("Thread has no stack");
  251.       return t_stack; 
  252. }
  253.  
  254. #endif /* __presto__threads_h__ */
  255.